#include <sstream>
#include "Utils/Tokenizer.hpp"
#include "Pizza.hpp"

namespace pizzeria {

Pizza::Pizza()
    : mPizzaRecipe(Regina) {
  mType = Regina;
  mSize = S;
}

Pizza::Pizza(PizzaType pizzaType, PizzaSize pizzaSize)
    : mPizzaRecipe(pizzaType) {
  mType = pizzaType;
  mSize = pizzaSize;
}

Pizza::Pizza(const Pizza &toCopy)
    : mPizzaRecipe(toCopy.mType) {
  mType = toCopy.mType;
  mSize = toCopy.mSize;
}

Pizza::~Pizza() {

}

Pizza &Pizza::operator =(const Pizza& toCopy) {
  if (this != &toCopy) {
    mType = toCopy.mType;
    mSize = toCopy.mSize;
    mPizzaRecipe = toCopy.mPizzaRecipe;
  }
  return *this;
}

Pizza::PizzaSize Pizza::GetSize() const {
  return mSize;
}

void Pizza::SetSize(PizzaSize size) {
  mSize = size;
}

Pizza::PizzaType Pizza::GetType() const {
  return mType;
}

void Pizza::SetType(PizzaType type) {
  mType = type;
}

std::list<std::string> Pizza::GetListOfValidTypeString() {
  static utils::Tokenizer tokenizer("regina margarita americaine fantasia");
  return tokenizer.GetTokensList();
}

std::list<std::string> Pizza::GetListOfValidSizeString() {
  static utils::Tokenizer tokenizer("S M L XL XXL");
  return tokenizer.GetTokensList();
}

const PizzaRecipe &Pizza::GetPizzaRecipe() const {
    return mPizzaRecipe;
  }

std::string Pizza::Serialize() const {
  std::ostringstream oss;

  int packedIntegers = (mType << 8) | (mSize);
  oss.write(reinterpret_cast<char *>(&packedIntegers), sizeof(int));
  return oss.str();
}

void Pizza::Deserialize(const std::string& data) {
  std::istringstream iss(data);
  int packed = 0;

  iss.read(reinterpret_cast<char *>(&packed), sizeof(int));
  mType = static_cast<pizzeria::Pizza::PizzaType>(packed >> 8 & 0xFF);
  mSize = static_cast<pizzeria::Pizza::PizzaSize>(packed & 0xFF);
}

size_t Pizza::GetSerializedSize() const {
  return (sizeof(int));
}

} /* !namespace pizzeria */
